﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Text.RegularExpressions;
using System.Text;


[ExecuteInEditMode]
[AddComponentMenu("UI/TextExtend")]
public class TextExtend : Text, IPointerClickHandler
{
    /// <summary>
    /// 用正则取  [图集ID#表情Tag] ID值==-1 ,表示为超链接
    /// </summary>
    private static readonly Regex _inputTagRegex = new Regex(@"\[(\-{0,1}\d{0,})#(.+?)(:{1}(.+?))?\]", RegexOptions.Singleline);
    private StringBuilder handleBuilder = new StringBuilder();
    private Dictionary<int, List<SpriteVertInfo>> SpriteVertInfos = new Dictionary<int, List<SpriteVertInfo>>();
    private readonly List<HrefInfo> _listHrefInfos = new List<HrefInfo>();
    UIVertex _tempVertex = UIVertex.simpleVert;
    //超链接点击区域
    public readonly List<Rect> Boxes = new List<Rect>();
    //计算定点信息的缓存数组
    private readonly UIVertex[] m_TempVerts = new UIVertex[4];

    Vector3[] conerPosition = new Vector3[4];
    private int instanceId;

    [TextArea]
    [SerializeField]
    protected string cacheText;

    public override string text
    {
        get
        {
            return m_Text;
        }
        set
        {
            string t = GetHandlerString(value);
            if (m_Text != t)
                m_Text = t;
        }
    }
    protected override void OnEnable()
    {
        base.OnEnable();
        supportRichText = true;
        alignByGeometry = true;
        rectTransform.GetLocalCorners(conerPosition);
        instanceId = this.GetInstanceID();

    }
    protected override void Start()
    {
        base.Start();
        //text = cacheText;
    }

    string GetHandlerString(string inputString)
    {
#if UNITY_EDITOR
        ReleaseSpriteTageInfo();
        ReleaseHrefInfos();
#endif
        if (string.IsNullOrEmpty(inputString))
            return "";
        handleBuilder.Remove(0, handleBuilder.Length);
        int textIndex = 0;
        var cllole = _inputTagRegex.Matches(inputString);
        int mixType = 0;
        SpriteInfoGroup tempGroup;
        foreach (Match match in cllole)
        {
            mixType = int.Parse(match.Groups[1].Value);
            if (mixType >= 0)    //图文混排
            {
                string tempTag = match.Groups[2].Value;
                tempGroup = MixRowHandle.Instance.IndexSpriteInfo[mixType][tempTag];
                string temp1 = inputString.Substring(textIndex, match.Index - textIndex);
                handleBuilder.Append(temp1);
                int tempIndex = handleBuilder.Length * 4;
                handleBuilder.Append(@"<quad size=" + tempGroup.Size + " width=" + tempGroup.Width + " />");
                SpriteVertInfo tempSpriteTag = Pool<SpriteVertInfo>.Get();
                tempSpriteTag.Index = tempIndex;
                tempSpriteTag.Id = mixType;
                tempSpriteTag.Tag = tempTag;
                tempSpriteTag.Size = new Vector2(tempGroup.Size * tempGroup.Width, tempGroup.Size);
                tempSpriteTag.UVs = tempGroup.ListSpriteInfos[0].UV;

                List<SpriteVertInfo> list;
                if (!SpriteVertInfos.TryGetValue(mixType, out list))
                {
                    list = new List<SpriteVertInfo>();
                    SpriteVertInfos.Add(mixType, list);
                }
                list.Add(tempSpriteTag);
            }
            else
            {
                handleBuilder.Append(inputString.Substring(textIndex, match.Index - textIndex));
                handleBuilder.Append("<color=blue>");
                int startIndex = handleBuilder.Length * 4;
                handleBuilder.Append(match.Groups[2].Value);
                int endIndex = handleBuilder.Length * 4 - 1;
                handleBuilder.Append("</color>");

                HrefInfo info = Pool<HrefInfo>.Get();
                info.Id = Mathf.Abs(mixType);
                info.StartIndex = startIndex;
                info.EndIndex = endIndex;
                info.HrefValue = match.Groups[3].Value;
                info.Name = match.Groups[2].Value;
                _listHrefInfos.Add(info);
            }
            textIndex = match.Index + match.Length;
        }
        handleBuilder.Append(inputString.Substring(textIndex, inputString.Length - textIndex));
        return handleBuilder.ToString();
    }

    private void DealHrefInfo(VertexHelper toFill)
    {
        GenerateClickRect(toFill);
        Vector2 extents = rectTransform.rect.size;
        var settings = GetGenerationSettings(extents);
        TextGenerator underlineText = Pool<TextGenerator>.Get();
        underlineText.Populate("_", settings);
        IList<UIVertex> tut = underlineText.verts;
        for (int m = 0; m < Boxes.Count; m++)
        {
            Vector3[] ulPos = new Vector3[4];
            ulPos[0] = Boxes[m].position + new Vector2(-fontSize * 0.5f, fontSize * 0.1f);
            ulPos[1] = Boxes[m].position + new Vector2(Boxes[m].width + fontSize / 2, fontSize * 0.1f);
            ulPos[2] = Boxes[m].position + new Vector2(Boxes[m].width + fontSize / 2, 0.0f);
            ulPos[3] = Boxes[m].position + new Vector2(-fontSize * 0.5f, 0);
            for (int j = 0; j < 4; j++)
            {
                m_TempVerts[j] = tut[j];
                m_TempVerts[j].color = Color.red;
                m_TempVerts[j].position = ulPos[j];
                if (j == 3)
                    toFill.AddUIVertexQuad(m_TempVerts);
            }
        }
        //回收下划线的对象
        Pool<TextGenerator>.Release(underlineText);
    }
    void GenerateClickRect(VertexHelper toFill)
    {
        float minX = 0, minY = 0, maxX = 0, maxY = 0;
        if (_listHrefInfos.Count > 0)
        {
            for (int i = 0; i < _listHrefInfos.Count; i++)
            {
                if (_listHrefInfos[i].StartIndex >= toFill.currentVertCount) continue;
                toFill.PopulateUIVertex(ref _tempVertex, _listHrefInfos[i].StartIndex + 1);
                var pos = _tempVertex.position;
                minX = pos.x;
                minY = pos.y;
                maxX = pos.x;
                maxY = pos.y;

                for (int j = _listHrefInfos[i].StartIndex + 1; j < _listHrefInfos[i].EndIndex; j++)
                {
                    if (j >= toFill.currentVertCount)
                    {
                        break;
                    }
                    toFill.PopulateUIVertex(ref _tempVertex, j);
                    pos = _tempVertex.position;
                    //Debug.Log("pos" + j + "  " + pos);
                    if (pos.y < minY)
                    {
                        if (maxY - pos.y > fontSize && Mathf.Abs(pos.x) >= conerPosition[3].x)
                        {
                            // Debug.Log("=============>" + pos);
                            Boxes.Add(new Rect(minX, minY, maxX - minX, maxY - minY));
                            minX = pos.x;
                            maxX = pos.x;
                            maxY = pos.y;
                        }

                        minY = pos.y;

                    }
                    if (pos.y > maxY)
                    {
                        maxY = pos.y;

                    }
                    if (pos.x < minX)
                    {
                        minX = pos.x;

                    }
                    if (pos.x > maxX)
                    {
                        maxX = pos.x;

                    }
                }


            }
            Boxes.Add(new Rect(minX, minY, maxX - minX, maxY - minY));
        }

    }
    private void DealSpriteTagInfo(VertexHelper toFill)
    {

        int index = -1;
        var enumerator = SpriteVertInfos.GetEnumerator();
        while (enumerator.MoveNext())
        {
            for (int i = 0; i < enumerator.Current.Value.Count; i++)
            {
                index = enumerator.Current.Value[i].Index;
                if ((index + 4) < toFill.currentVertCount)
                {
                    for (int j = index; j < index + 4; j++)
                    {
                        toFill.PopulateUIVertex(ref _tempVertex, j);
                        //清理多余的乱码uv
                        _tempVertex.uv0 = Vector2.zero;
                        //获取quad的位置 --> 转为世界坐标
                        enumerator.Current.Value[i].Pos[j - index] = Utility.TransformPoint2World(transform, _tempVertex.position);
                        toFill.SetUIVertex(_tempVertex, j);
                    }

                }
            }
        }

    }
    private void UpdateDrawSprite()
    {
        //记录之前的信息
        foreach (var SpriteVertInfoList in SpriteVertInfos)
        {
            if (SpriteVertInfoList.Value.Count <= 0)
                continue;
            MixRowHandle.Instance.UpdateMeshInfo(instanceId, SpriteVertInfoList.Key, SpriteVertInfoList.Value);
        }

    }

    public void RecycleReset()
    {
        m_Text = "";
        var enumerator = SpriteVertInfos.GetEnumerator();
        while (enumerator.MoveNext())
        {
            enumerator.Current.Value.Clear();
        }
        MixRowHandle.Instance.ClearDrawData(instanceId);
    }

    protected override void OnPopulateMesh(VertexHelper toFill)
    {
        if (font == null)
            return;
        base.OnPopulateMesh(toFill);

        m_DisableFontTextureRebuiltCallback = true;
        //更新顶点位置&去掉乱码uv
        DealSpriteTagInfo(toFill);

        DealHrefInfo(toFill);
        m_DisableFontTextureRebuiltCallback = false;
        UpdateDrawSprite();
    }

    //回收SpriteTagInfo
    private void ReleaseSpriteTageInfo()
    {
        //记录之前的信息
        var enumerator = SpriteVertInfos.GetEnumerator();
        while (enumerator.MoveNext())
        {
            for (int i = 0; i < enumerator.Current.Value.Count; i++)
            {
                Pool<SpriteVertInfo>.Release(enumerator.Current.Value[i]);
            }
            enumerator.Current.Value.Clear();
        }
        SpriteVertInfos.Clear();
    }
    //回收超链接的信息
    private void ReleaseHrefInfos()
    {
        for (int i = 0; i < _listHrefInfos.Count; i++)
        {
            Pool<HrefInfo>.Release(_listHrefInfos[i]);
        }
        _listHrefInfos.Clear();
    }
    public void OnPointerClick(PointerEventData eventData)
    {
        Vector2 lp;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            rectTransform, eventData.position, eventData.pressEventCamera, out lp);
        foreach (var item in Boxes)
        {
            if (item.Contains(lp))
            {
                Debug.Log("chufa");
                return;
            }
        }
    }
}

public class SpriteVertInfo
{
    /// <summary>
    /// 顶点索引id
    /// </summary>
    public int Index;
    /// <summary>
    /// 图集id
    /// </summary>
    public int Id;
    /// <summary>
    /// 标签标签
    /// </summary>
    public string Tag;
    /// <summary>
    /// 标签大小
    /// </summary>
    public Vector2 Size;
    /// <summary>
    /// 表情位置
    /// </summary>
    public Vector3[] Pos = new Vector3[4];
    /// <summary>
    /// uv
    /// </summary>
    public Vector2[] UVs = new Vector2[4];
}
/// <summary>
/// 超链接信息类
/// </summary>
public class HrefInfo
{
    /// <summary>
    /// 超链接id
    /// </summary>
    public int Id;
    /// <summary>
    /// 顶点开始索引值
    /// </summary>
    public int StartIndex;
    /// <summary>
    /// 顶点结束索引值
    /// </summary>
    public int EndIndex;
    /// <summary>
    /// 名称
    /// </summary>
    public string Name;
    /// <summary>
    /// 超链接的值
    /// </summary>
    public string HrefValue;
    /// <summary>
    /// 碰撞盒范围
    /// </summary>
    //public readonly List<Rect> Boxes = new List<Rect>();
    //public Rect box;
}